/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package studio.raptor.ddal.core.transaction;

import com.google.common.base.Joiner;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.RollingFileAppender;
import org.apache.logging.log4j.core.appender.rolling.SizeBasedTriggeringPolicy;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.layout.PatternLayout;

import studio.raptor.ddal.common.util.StringUtil;

/**
 * 实现硬编码Log4j2配置。对应Log4j2版本是2.7，因log4j2版本间差异不小，所以
 * 在选择版本时一定要考虑API的兼容性。
 *
 * @author Sam
 * @since 3.0.0
 */
abstract class AbstractTransactionLogger implements TransactionLogger {

  static final String LOG_SUFFIX = "log";
  static final Joiner DOT_JOINER = Joiner.on('.');
  static final String ARCHIVE_LAYOUT_PATTERN = DOT_JOINER.join(new String[]{"%d{yyyy-MM-dd}", "%i"});

  private String logPath;
  private String logName;
  private String fileName;
  private String filePattern;
  private String fileRollingSize;

  AbstractTransactionLogger(String logPath, String logName, String fileName,
                            String filePattern, String fileRollingSize) {
    this.logPath = logPath;
    this.logName = logName;
    this.fileName = fileName;
    this.filePattern = filePattern;
    this.fileRollingSize = fileRollingSize;
    if (StringUtil.isEmpty(this.fileRollingSize)) {
      this.fileRollingSize = "5MB";
    }
  }

  static {
    Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
      @Override
      public void run() {
        try {
          Thread.sleep(2000);
          final org.apache.logging.log4j.spi.LoggerContext loggerContext = LogManager.getContext(false);
          if(loggerContext instanceof LoggerContext) {
            ((LoggerContext)loggerContext).stop();
          }
        } catch (Exception ignored) {
        }
      }
    }, "LogbackShutdownHook"));
  }

  // fixme
  void registerLogConfig() {
//    final LoggerContext loggerContext = (LoggerContext) LogManager.getContext(false);
//    final Configuration config = loggerContext.getConfiguration();
//
//    RollingFileAppender appender = createRollingFileAppender(config, logPath);
//    appender.start();
//    config.addAppender(appender);
//
//    AppenderRef ref = AppenderRef.createAppenderRef("File", null, null);
//    LoggerConfig loggerConfig = LoggerConfig.createLogger(false, Level.INFO, logName, null, new AppenderRef[]{ref}, null, config, null);
//    loggerConfig.addAppender(appender, null, null);
//    config.addLogger(logName, loggerConfig);
//
//    loggerContext.updateLoggers();
  }

  private PatternLayout createPatterLayout() {
    return PatternLayout.newBuilder().withPattern("%d{COMPACT}|%m%n").build();
  }

  private RollingFileAppender createRollingFileAppender(Configuration config, String logPath) {
    RollingFileAppender.Builder builder = new RollingFileAppender.Builder()
            .withFileName(logPath + "/" + fileName)
            .withAppend(true)
            .withConfiguration(config)
            .withLocking(false);
    builder.withLayout(createPatterLayout());
    builder.withImmediateFlush(true);
    builder.withIgnoreExceptions(false);
    builder.withBufferedIo(true);
    builder.withBufferSize(4000);
    builder.withFilter(null);
    builder.withAdvertise(false);
    builder.withName(logName);
    builder.withFilePattern(logPath + "/" + filePattern);
    builder.withPolicy(SizeBasedTriggeringPolicy.createPolicy(fileRollingSize));
    return builder.build();
  }
}
